home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xpaint-2.1.1 / readRC.c < prev    next >
C/C++ Source or Header  |  1995-05-03  |  8KB  |  375 lines

  1. /* +-------------------------------------------------------------------+ */
  2. /* | Copyright 1993, David Koblas (koblas@netcom.com)                  | */
  3. /* |                                                                   | */
  4. /* | Permission to use, copy, modify, and to distribute this software  | */
  5. /* | and its documentation for any purpose is hereby granted without   | */
  6. /* | fee, provided that the above copyright notice appear in all       | */
  7. /* | copies and that both that copyright notice and this permission    | */
  8. /* | notice appear in supporting documentation.  There is no           | */
  9. /* | representations about the suitability of this software for        | */
  10. /* | any purpose.  this software is provided "as is" without express   | */
  11. /* | or implied warranty.                                              | */
  12. /* |                                                                   | */
  13. /* +-------------------------------------------------------------------+ */
  14.  
  15. #include <stdio.h>
  16. #include <pwd.h>
  17. #include <ctype.h>
  18. #include <X11/Intrinsic.h>
  19. #include <X11/Xos.h>
  20. #include <sys/stat.h>
  21. #include "image.h"
  22. #include "rc.h"
  23.  
  24. #ifndef NOSTDHDRS
  25. #include <stdlib.h>
  26. #include <unistd.h>
  27. #endif
  28.  
  29. extern char    *mktemp(char*);
  30. extern void    StrToArgv(char*, int*, char**);
  31. extern char    *GetDefaultRC(void);
  32.  
  33. #define RC_FILENAME    ".XPaintrc"
  34.  
  35. static String    defaultRC[] = {
  36. #include "DefaultRC.txt.h"
  37. };
  38.  
  39. /*
  40. **   RC File Syntax
  41. **
  42. **     brush   [ BeginData\n ... \nEndData | filename ]
  43. **
  44. **     pattern [ BeginData\n ... \nEndData | filename ]
  45. **
  46. **     solid   [ name | x-rgb-def | r g b ]
  47. **     
  48. **     \n# -- comment
  49. */
  50.  
  51. #define EQ(a,b)        (strcasecmp(a,b) == 0)
  52.  
  53. static int    tempIndex = -1;
  54. static char    *tempName[10];
  55. static RCInfo    *baseInfo = NULL;
  56.  
  57. static FILE    *openTemp(char **np)
  58. {
  59.     char        *n;
  60.     char        xx[256];
  61.  
  62.     if ((n = getenv("TMPDIR")) == NULL)
  63.         n = "/tmp";
  64.  
  65.     strcpy(xx, n);
  66.     strcat(xx, "/XPaintXXXXXXX");
  67.     n = mktemp(xx);
  68.     tempName[++tempIndex] = XtNewString(n);
  69.     if (np != NULL)
  70.         *np = tempName[tempIndex];
  71.     return fopen(tempName[tempIndex], "w");
  72. }
  73. static void    removeTemp()
  74. {
  75.     if (tempIndex < 0)
  76.         return;
  77.     if (tempName[tempIndex] != NULL) {
  78.         unlink(tempName[tempIndex]);
  79.         XtFree((XtPointer)tempName[tempIndex]);
  80.     }
  81.     tempName[tempIndex--] = NULL;
  82. }
  83.  
  84. static void addImage(RCInfo *info, Image *image, Boolean isBrush)
  85. {
  86.     if (isBrush) {
  87.         info->brushes = (Image**)XtRealloc((XtPointer)info->brushes, (info->nbrushes + 1) * sizeof(Image*));
  88.         info->brushes[info->nbrushes++] = image;
  89.     } else {
  90.         info->images = (Image**)XtRealloc((XtPointer)info->images, (info->nimages + 1) * sizeof(Image*));
  91.         info->images[info->nimages++] = image;
  92.     }
  93. }
  94. static void addSolid(RCInfo *info, char *color)
  95. {
  96.     info->colors = (char**)XtRealloc((XtPointer)info->colors, (info->ncolors + 1) * sizeof(char*));
  97.     info->colors[info->ncolors++] = XtNewString(color);
  98. }
  99.  
  100. static RCInfo *makeInfo()
  101. {
  102.     RCInfo    *info;
  103.  
  104.     info = XtNew(RCInfo);
  105.     info->freed = False;
  106.     info->nimages = 0;
  107.     info->nbrushes = 0;
  108.     info->colorFlags = NULL;
  109.     info->colorPixels = NULL;
  110.     info->images  = XtNew(Image*);
  111.     info->brushes = XtNew(Image*);
  112.     info->ncolors = 0;
  113.     info->colors = XtNew(char*);
  114.  
  115.     baseInfo = info;
  116.  
  117.     return info;
  118. }
  119.  
  120. void FreeRC(RCInfo *info)
  121. {
  122.     int    i;
  123.  
  124.     if (info->colors != NULL) {
  125.         for (i = 0; i < info->ncolors; i++)
  126.             XtFree((XtPointer)info->colors[i]);
  127.         XtFree((XtPointer)info->colors);
  128.     }
  129.     if (info->colorFlags != NULL)
  130.         XtFree((XtPointer)info->colorFlags);
  131.     if (info->colorPixels != NULL)
  132.         XtFree((XtPointer)info->colorPixels);
  133.  
  134.     for (i = 0; i < info->nimages; i++)
  135.         ImageDelete(info->images[i]);
  136.     if (info->images != NULL)
  137.         XtFree((XtPointer)info->images);
  138.  
  139.     for (i = 0; i < info->nbrushes; i++)
  140.         ImageDelete(info->brushes[i]);
  141.     if (info->brushes != NULL)
  142.         XtFree((XtPointer)info->brushes);
  143.  
  144.     XtFree((XtPointer)info);
  145.  
  146.     if (info == baseInfo)
  147.         baseInfo = NULL;
  148. }
  149.  
  150.  
  151. static char    *expand(char *path)
  152. {
  153.     static char    out[512];
  154.     char        name[80];
  155.     char        *pp = path, *cp;
  156.     struct passwd    *pw;
  157.  
  158.     if (*path != '~')
  159.         return path;
  160.     path++;
  161.     cp = name;
  162.     while (*pp != '/' && *pp != '\0')
  163.         *cp++ = *pp++;
  164.     *cp = '\0';
  165.     if (name[0] == '\0') {
  166.         pw = getpwuid(getuid());
  167.     } else {
  168.         pw = getpwnam(name);
  169.     }
  170.     if (pw == NULL)
  171.         return path;
  172.     strcpy(out, pw->pw_dir);
  173.     strcat(out, "/");
  174.     strcat(out, pp);
  175.  
  176.     return out;
  177. }
  178.  
  179. static Boolean readRC(RCInfo **info, char *file)
  180. {
  181.     FILE    *fd = fopen(file, "r");
  182.     char    buf[512];
  183.     int    lineno = 0;
  184.     int    argc;
  185.     char    *argv[128 + 2];
  186.  
  187.     if (fd == NULL)
  188.         return False;
  189.  
  190.     while (fgets(buf, sizeof(buf), fd) != NULL) {
  191.         lineno++;
  192.         if (buf[0] == '#' || buf[0] == '!')
  193.             continue;
  194.         StrToArgv(buf, &argc, argv);
  195.         if (argc == 0)
  196.             continue;
  197.         if (EQ(argv[0], "reset")) {
  198.             FreeRC(*info);
  199.             *info = makeInfo();
  200.         } else if (EQ(argv[0], "solid")) {
  201.             addSolid(*info, argv[1]);
  202.         } else if (EQ(argv[0], "pattern") || EQ(argv[0], "brush")) {
  203.             extern Image    *ReadMagic(char*);
  204.             char        *nm;
  205.             Image        *image;
  206.  
  207.             if (EQ(argv[1], "BeginData")) {
  208.                 FILE    *ofd;
  209.                 
  210.                 ofd = openTemp(&nm);
  211.                 while (fgets(buf, sizeof(buf), fd) != NULL) {
  212.                     if (strncmp(buf, "EndData", 7) == 0)
  213.                         break;
  214.                     if (ofd != NULL)
  215.                         fputs(buf, ofd);
  216.                 }
  217.                 if (ofd != NULL) {
  218.                     fclose(ofd);
  219.                 } else {
  220.                     removeTemp();
  221.                     continue;
  222.                 }
  223.             } else {
  224.                 nm = expand(argv[1]);
  225.             }
  226.  
  227.             if ((image = ReadMagic(nm)) != NULL)
  228.                 addImage(*info, image, EQ(argv[0], "brush"));
  229.  
  230.             removeTemp();
  231.         }
  232.     }
  233.  
  234.     return True;
  235. }
  236.  
  237. /*
  238. **  Simple RC reading strategy:
  239. **    load default
  240. **    append users ~/.XPaintrc
  241. **    append users ./.XPaintrc
  242. **
  243. */
  244. RCInfo    *ReadDefaultRC()
  245. {
  246.     static Boolean    inited = False;
  247.     static Boolean    have[2] = { False, False };
  248.     static time_t    lastMtime;
  249.     static RCInfo    *info = NULL;
  250.     static char    homeRC[256];
  251.     FILE        *fd;
  252.     int        i;
  253.     char        *tn;
  254.     struct passwd    *pw = getpwuid(getuid());
  255.     struct stat    statbufA, statbufB;
  256.     char        *rcf;
  257.  
  258.     if (!inited) {
  259.         inited = True;
  260.         if (pw != NULL && pw->pw_dir != NULL) {
  261.             strcpy(homeRC, pw->pw_dir);
  262.             strcat(homeRC, "/");
  263.             strcat(homeRC, RC_FILENAME);
  264.         } else {
  265.             homeRC[0] = '\0';
  266.         }
  267.     }
  268.  
  269.     if ((rcf = GetDefaultRC()) != NULL) {
  270.         if (stat(rcf, &statbufA) < 0)    /* missing file? */
  271.             goto readit;
  272.  
  273.         if (info == NULL || statbufA.st_mtime > lastMtime) {
  274.             info = makeInfo();
  275.             readRC(&info, rcf);
  276.             lastMtime = statbufA.st_mtime;
  277.         }
  278.     } else {
  279.         if (info != NULL) {
  280.             Boolean    read = False;
  281.             Boolean    hA, hB;
  282.  
  283.             hA = (stat(homeRC, &statbufA) >= 0);
  284.             hB = (stat(RC_FILENAME, &statbufB) >= 0);
  285.  
  286.             if (hA != have[0] || hB != have[1])
  287.                 goto readit;
  288.             
  289.             if (hA && statbufA.st_mtime > lastMtime)
  290.                 goto readit;
  291.             if (hB && statbufB.st_mtime > lastMtime)
  292.                 goto readit;
  293.  
  294.             /*
  295.             **  No change
  296.             */
  297.             return info;
  298.         }
  299. readit:
  300.         if (info != NULL)
  301.             FreeRC(info);
  302.         info = makeInfo();
  303.  
  304.         /*
  305.         **  Set time information
  306.         */
  307.         have[0] = (stat(homeRC, &statbufA) >= 0);
  308.         have[1] = (stat(RC_FILENAME, &statbufB) >= 0);
  309.  
  310.         if (have[0] && have[1]) {
  311.             if (statbufA.st_mtime > statbufB.st_mtime)
  312.                 lastMtime = statbufA.st_mtime;
  313.             else
  314.                 lastMtime = statbufB.st_mtime;
  315.         } else if (have[0]) {
  316.             lastMtime = statbufA.st_mtime;
  317.         } else if (have[1]) {
  318.             lastMtime = statbufB.st_mtime;
  319.         }
  320.  
  321.         /*
  322.         **  Load the default RC
  323.         */
  324.         if ((fd = openTemp(&tn)) != NULL) {
  325.             for (i = 0; i < XtNumber(defaultRC); i++) {
  326.                 fputs(defaultRC[i], fd);
  327.                 putc('\n', fd);
  328.             }
  329.             fclose(fd);
  330.  
  331.             readRC(&info, tn);
  332.             removeTemp();
  333.         }
  334.  
  335.         /*
  336.         **  Load ~/.XPaintrc
  337.         */
  338.         if (homeRC[0] != '\0')
  339.             readRC(&info, homeRC);
  340.  
  341.         /*
  342.         **  Load ".XPaintrc"
  343.         */
  344.         readRC(&info, RC_FILENAME);
  345.     }
  346.  
  347.     if (info->ncolors == 0 && info->nimages == 0) {
  348.         addSolid(info, "black");
  349.         addSolid(info, "white");
  350.         addSolid(info, "red");
  351.         addSolid(info, "green");
  352.         addSolid(info, "blue");
  353.         addSolid(info, "cyan");
  354.         addSolid(info, "magenta");
  355.         addSolid(info, "yellow");
  356.     }
  357.  
  358.     return info;
  359. }
  360.  
  361. RCInfo *ReadRC(char *file)
  362. {
  363.     RCInfo    *info = makeInfo();
  364.  
  365.     if (!readRC(&info, file)) {
  366.         /*
  367.         **  Error occured
  368.         */
  369.         FreeRC(info);
  370.         return NULL;
  371.     }
  372.  
  373.     return info;
  374. }
  375.